// Copyright 2019 Google LLC.
#include "include/core/SkColor.h"
#include "include/core/SkFontStyle.h"
#include "modules/skparagraph/include/TextStyle.h"

namespace skia {
namespace textlayout {

//const std::vector<SkString>* TextStyle::kDefaultFontFamilies =
//        new std::vector<SkString>{SkString(DEFAULT_FONT_FAMILY)};

TextStyle TextStyle::cloneForPlaceholder() {
    TextStyle result;
    result.fColor = fColor;
    result.fFontSize = fFontSize;
    result.fFontFamilies = fFontFamilies;
    result.fDecoration = fDecoration;
    result.fHasBackground = fHasBackground;
    result.fHasForeground = fHasForeground;
    result.fBackground = fBackground;
    result.fForeground = fForeground;
    result.fHeightOverride = fHeightOverride;
    result.fIsPlaceholder = true;
    result.fFontFeatures = fFontFeatures;
    result.fHalfLeading = fHalfLeading;
    result.fBaselineShift = fBaselineShift;
    result.fFontArguments = fFontArguments;
    return result;
}

bool TextStyle::equals(const TextStyle& other) const {
    return OH_Drawing_TextStyleIsEqual(*this, other);
//     if (fIsPlaceholder || other.fIsPlaceholder) {
//         return false;
//     }
//
//     if (fColor != other.fColor) {
//         return false;
//     }
//     if (!(fDecoration == other.fDecoration)) {
//         return false;
//     }
//     if (!(fFontStyle == other.fFontStyle)) {
//         return false;
//     }
//     if (fFontFamilies != other.fFontFamilies) {
//         return false;
//     }
//     if (fLetterSpacing != other.fLetterSpacing) {
//         return false;
//     }
//     if (fWordSpacing != other.fWordSpacing) {
//         return false;
//     }
//     if (fHeight != other.fHeight) {
//         return false;
//     }
//     if (fHeightOverride != other.fHeightOverride) {
//         return false;
//     }
//     if (fHalfLeading != other.fHalfLeading) {
//         return false;
//     }
//     if (fBaselineShift != other.fBaselineShift) {
//         return false;
//     }
//     if (fFontSize != other.fFontSize) {
//         return false;
//     }
//     if (fLocale != other.fLocale) {
//         return false;
//     }
//     if (fHasForeground != other.fHasForeground || fForeground != other.fForeground) {
//         return false;
//     }
//     if (fHasBackground != other.fHasBackground || fBackground != other.fBackground) {
//         return false;
//     }
// //     if (fTextShadows.size() != other.fTextShadows.size()) {
// //         return false;
// //     }
// //     for (size_t i = 0; i < fTextShadows.size(); ++i) {
// //         if (fTextShadows[i] != other.fTextShadows[i]) {
// //             return false;
// //         }
// //     }
//     if (fFontFeatures.size() != other.fFontFeatures.size()) {
//         return false;
//     }
//     for (size_t i = 0; i < fFontFeatures.size(); ++i) {
//         if (!(fFontFeatures[i] == other.fFontFeatures[i])) {
//             return false;
//         }
//     }
//     if (fFontArguments != other.fFontArguments) {
//         return false;
//     }
//
//     return true;
}

bool TextStyle::equalsByFonts(const TextStyle& that) const {
    return OH_Drawing_TextStyleIsEqualByFont(*this, that);
//     return !fIsPlaceholder && !that.fIsPlaceholder &&
//            fFontStyle == that.fFontStyle &&
//            fFontFamilies == that.fFontFamilies &&
//            fFontFeatures == that.fFontFeatures &&
//            fFontArguments == that.getFontArguments() &&
//            nearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
//            nearlyEqual(fWordSpacing, that.fWordSpacing) &&
//            nearlyEqual(fHeight, that.fHeight) &&
//            nearlyEqual(fBaselineShift, that.fBaselineShift) &&
//            nearlyEqual(fFontSize, that.fFontSize) &&
//            fLocale == that.fLocale;
}

bool TextStyle::matchOneAttribute(StyleType styleType, const TextStyle& other) const {
    static_assert((int)StyleType::kNone == OH_Drawing_TextStyleType::TEXT_STYLE_NONE, "TextStyleType not equal!");
    static_assert((int)StyleType::kAllAttributes == OH_Drawing_TextStyleType::TEXT_STYLE_ALL_ATTRIBUTES, "TextStyleType not equal!");
    static_assert((int)StyleType::kFont == OH_Drawing_TextStyleType::TEXT_STYLE_FONT, "TextStyleType not equal!");
    static_assert((int)StyleType::kForeground == OH_Drawing_TextStyleType::TEXT_STYLE_FOREGROUND, "TextStyleType not equal!");
    static_assert((int)StyleType::kBackground == OH_Drawing_TextStyleType::TEXT_STYLE_BACKGROUND, "TextStyleType not equal!");
    static_assert((int)StyleType::kShadow == OH_Drawing_TextStyleType::TEXT_STYLE_SHADOW, "TextStyleType not equal!");
    static_assert((int)StyleType::kDecorations == OH_Drawing_TextStyleType::TEXT_STYLE_DECORATIONS, "TextStyleType not equal!");
    static_assert((int)StyleType::kLetterSpacing == OH_Drawing_TextStyleType::TEXT_STYLE_LETTER_SPACING, "TextStyleType not equal!");
    static_assert((int)StyleType::kWordSpacing == OH_Drawing_TextStyleType::TEXT_STYLE_WORD_SPACING, "TextStyleType not equal!");

    return OH_Drawing_TextStyleIsAttributeMatched(*this, other, (OH_Drawing_TextStyleType)styleType);
//     switch (styleType) {
//         case kForeground:
//             return (!fHasForeground && !other.fHasForeground && fColor == other.fColor) ||
//                    ( fHasForeground &&  other.fHasForeground && fForeground == other.fForeground);
//
//         case kBackground:
//             return (!fHasBackground && !other.fHasBackground) ||
//                    ( fHasBackground &&  other.fHasBackground && fBackground == other.fBackground);
//
//         case kShadow:
//             if (fTextShadows.size() != other.fTextShadows.size()) {
//                 return false;
//             }
//
//             for (int32_t i = 0; i < SkToInt(fTextShadows.size()); ++i) {
//                 if (fTextShadows[i] != other.fTextShadows[i]) {
//                     return false;
//                 }
//             }
//             return true;
//
//         case kDecorations:
//             return this->fDecoration == other.fDecoration;
//
//         case kLetterSpacing:
//             return fLetterSpacing == other.fLetterSpacing;
//
//         case kWordSpacing:
//             return fWordSpacing == other.fWordSpacing;
//
//         case kAllAttributes:
//             return this->equals(other);
//
//         case kFont:
//             // TODO: should not we take typefaces in account?
//             return fFontStyle == other.fFontStyle &&
//                    fLocale == other.fLocale &&
//                    fFontFamilies == other.fFontFamilies &&
//                    fFontSize == other.fFontSize &&
//                    fHeight == other.fHeight &&
//                    fHalfLeading == other.fHalfLeading &&
//                    fBaselineShift == other.fBaselineShift &&
//                    fFontArguments == other.fFontArguments;
//         default:
//             SkASSERT(false);
//             return false;
//     }
}

void TextStyle::getFontMetrics(SkFontMetrics* metrics) const {
    SkFont font(fTypeface, fFontSize);
    font.setEdging(fFontRastrSettings.fEdging);
    font.setSubpixel(fFontRastrSettings.fSubpixel);
    font.setHinting(fFontRastrSettings.fHinting);
    font.getMetrics(metrics);
    if (fHeightOverride) {
        auto multiplier = fHeight * fFontSize;
        auto height = metrics->fDescent - metrics->fAscent + metrics->fLeading;
        metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2) * multiplier / height;
        metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2) * multiplier / height;

    } else {
        metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2);
        metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2);
    }
    // If we shift the baseline we need to make sure the shifted text fits the line
    metrics->fAscent += fBaselineShift;
    metrics->fDescent += fBaselineShift;
}

void TextStyle::setFontArguments(const std::optional<SkFontArguments>& args) {
    if (!args) {
        fFontArguments.reset();
        return;
    }

    fFontArguments.emplace(*args);
}

void TextStyle::fillOHOSStyle() {
    if (fColor != SK_ColorWHITE) {
        setColor(fColor);
    }
    if (fHasForeground) {
        setForegroundPaint(std::get<SkPaint>(fForeground));
    }
    if (fHasBackground) {
        setBackgroundPaint(std::get<SkPaint>(fBackground));
    }
    if (fDecoration.fType != TextDecoration::kNoDecoration) {
        setDecoration(fDecoration.fType);
    }
//     setDecorationMode(fDecoration.fMode);
    if (fDecoration.fStyle != TextDecorationStyle::kSolid) {
        setDecorationStyle(fDecoration.fStyle);
    }
    if (fDecoration.fColor != SK_ColorTRANSPARENT) {
        setDecorationColor(fDecoration.fColor);
    }
    if (!SkScalarNearlyEqual(fDecoration.fThicknessMultiplier, 1.0f)) {
        setDecorationThicknessMultiplier(fDecoration.fThicknessMultiplier);
    }
    if (!(fFontStyle == SkFontStyle())) {
        setFontStyle(fFontStyle);
    }
//     setFontArguments();
    if (!SkScalarNearlyEqual(fFontSize, 14.0f)) {
        setFontSize(fFontSize);
    }
    if (!(fFontFamilies.size() == 1 && fFontFamilies[0].equals(DEFAULT_FONT_FAMILY))) {
        setFontFamilies(fFontFamilies);
    }
    if (!SkScalarNearlyZero(fBaselineShift)) {
        setBaselineShift(fBaselineShift);
    }
    if (!SkScalarNearlyEqual(fHeight, 1.0f)) {
        setHeight(fHeight);
    }
//     setHeightOverride(fHeightOverride);
    if (fHalfLeading) {
        setHalfLeading(fHalfLeading);
    }
    if (!SkScalarNearlyZero(fLetterSpacing)) {
        setLetterSpacing(fLetterSpacing);
    }
    if (!SkScalarNearlyZero(fWordSpacing)) {
        setWordSpacing(fWordSpacing);
    }
//     setTypeface(fTypeface);
//     setFontRastrSettings(fFontRastrSettings);
    if (!fLocale.isEmpty()) {
        setLocale(fLocale);
    }
    if (fTextBaseline != TextBaseline::kAlphabetic) {
        setTextBaseline(fTextBaseline);
    }
    if (fIsPlaceholder) {
        setPlaceholder();
    }
    if (!fFontFeatures.empty()) {
        for (const auto &ff : fFontFeatures) {
            addFontFeatureOHOS(ff);
        }
    }
    if (!fTextShadows.empty()) {
        for (const auto &ts : fTextShadows) {
            addShadowOHOS(ts);
        }
    }
}

bool PlaceholderStyle::equals(const PlaceholderStyle& other) const {
    return nearlyEqual(fWidth, other.fWidth) &&
           nearlyEqual(fHeight, other.fHeight) &&
           fAlignment == other.fAlignment &&
           fBaseline == other.fBaseline &&
           (fAlignment != PlaceholderAlignment::kBaseline ||
            nearlyEqual(fBaselineOffset, other.fBaselineOffset));
}

}  // namespace textlayout
}  // namespace skia
